package org.example.Proxy;

import cn.hutool.core.lang.Console;
import io.netty.bootstrap.Bootstrap; // 导入Netty的Bootstrap类，用于创建客户端连接
import io.netty.buffer.ByteBuf; // 导入Netty的ByteBuf类，用于网络数据的缓冲区
import io.netty.channel.*; // 导入Netty的Channel相关类和接口
import io.netty.channel.nio.NioEventLoopGroup; // 导入Netty的NioEventLoopGroup类，用于处理I/O操作
import io.netty.channel.socket.nio.NioSocketChannel; // 导入Netty的NioSocketChannel类，用于创建NIO套接字通道

// 自定义的代理服务器处理器
public class ProxyServerHandler extends ChannelInboundHandlerAdapter {

    // 创建一个工作线程组，用于处理与目标服务器的连接和数据传输
    private final EventLoopGroup workerGroup = new NioEventLoopGroup();
    // 定义一个出站通道，用于与目标服务器的连接
    private Channel outboundChannel;

    // 当代理服务器与客户端的连接变为活跃状态时触发
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        Console.log("channelActive");
        // 获取与客户端的入站通道
        final Channel inboundChannel = ctx.channel();

        // 创建一个Bootstrap实例，用于连接到目标服务器
        Bootstrap b = new Bootstrap();
        b.group(workerGroup); // 设置工作线程组
        b.channel(NioSocketChannel.class); // 设置通道类型为NIO套接字通道
        b.handler(new ChannelInitializer<Channel>() { // 设置通道初始化器
            @Override
            public void initChannel(Channel ch) throws Exception {
                // 为与目标服务器的连接设置出站处理器，用于处理从目标服务器接收到的数据
                ch.pipeline().addLast(new OutboundHandler(inboundChannel));
            }
        });

        // 连接到目标服务器localhost:3000
        b.connect("localhost", 3000).addListener((ChannelFutureListener) future -> {
            // 连接成功时，将出站通道设置为与目标服务器的连接通道
            if (future.isSuccess()) {
                outboundChannel = future.channel();
            } else { // 连接失败时，关闭与客户端的连接
                inboundChannel.close();
            }
        });
    }

    // 当代理服务器从客户端接收到数据时触发
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        Console.log("channelRead");
        // 如果与目标服务器的连接是活跃的
        if (outboundChannel.isActive()) {
            // 将接收到的数据转发给目标服务器
            outboundChannel.writeAndFlush(msg).addListener((ChannelFutureListener) future -> {
                // 如果转发失败，关闭与客户端的连接
                if (!future.isSuccess()) {
                    ctx.close();
                }
            });
        }
    }

    // 当与客户端的连接变为非活跃状态时触发
    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        Console.log("channelInactive");
        // 如果与目标服务器的连接存在，则关闭它
        if (outboundChannel != null) {
            outboundChannel.close();
        }
    }

    // 当在处理过程中发生异常时触发
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        Console.log("exceptionCaught");
        // 打印异常堆栈信息
        cause.printStackTrace();
        // 关闭发生异常的通道
        ctx.close();
    }

    // 自定义的出站处理器，用于处理从目标服务器接收到的数据
    private static class OutboundHandler extends ChannelInboundHandlerAdapter {
        // 持有与客户端的连接通道，用于将数据转发回客户端
        private final Channel inboundChannel;

        // 构造函数，初始化与客户端的连接通道
        public OutboundHandler(Channel inboundChannel) {
            this.inboundChannel = inboundChannel;
        }

        // 当从目标服务器接收到数据时触发
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) {
            Console.log("OutboundHandler channelRead");
            // 将接收到的数据转发给客户端
            inboundChannel.writeAndFlush(msg).addListener((ChannelFutureListener) future -> {
                // 如果转发失败，关闭与目标服务器的连接
                if (!future.isSuccess()) {
                    ctx.close();
                }
            });
        }

        // 当在处理过程中发生异常时触发
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            Console.log("OutboundHandler exceptionCaught");
            // 打印异常堆栈信息
            cause.printStackTrace();
            // 关闭发生异常的通道
            ctx.close();
        }
    }
}